﻿using System;
using System.Collections.Generic;
using System.IO;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit.RevitExtension;
using YJKDrawTool;
using YJKRevitView;

namespace YArchitech.Revit.MEP.Opening
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class CmdDrivepipeDim : IExternalCommand
	{
		public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elems)
		{
			try
			{
				CmdViewType types = (CmdViewType)3;
				if (SwitchView.SetUsableView(types, cmdData) != Autodesk.Revit.UI.Result.Succeeded)
				{
					return Autodesk.Revit.UI.Result.Failed;
				}
				UIDocument activeUIDocument = cmdData.Application.ActiveUIDocument;
                this.m_LineStyle = LineTypeTool.CreateLineType(activeUIDocument.Document, "红色交叉线", new Autodesk.Revit.DB.Color(byte.MaxValue, 0, 0), 1, (GraphicsStyleType)1);
				this.GetAllOpeningDim(activeUIDocument.Document);
				List<Element> list = new List<Element>();
				while (this.SelectDrivepipe(activeUIDocument, list))
				{
					if (list.Count == 1)
					{
						this.DimSingleDrivepipe(activeUIDocument, list[0]);
					}
					else if (list.Count > 1)
					{
						this.DimMultiDrivepipe(activeUIDocument, list);
					}
				}
				LineTypeTool.DeleteLineType(activeUIDocument.Document, "红色交叉线");
			}
			catch
			{
				LineTypeTool.DeleteLineType(cmdData.Application.ActiveUIDocument.Document, "红色交叉线");
				return Autodesk.Revit.UI.Result.Failed;
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private bool SelectDrivepipe(UIDocument UIDoc, List<Element> lstSelDrivepipe)
		{
			try
			{
				DrivepipeFilter drivepipeFilter = new DrivepipeFilter();
				IEnumerable<Element> enumerable = UIDoc.Selection.PickElementsByRectangle(drivepipeFilter, "请框选套管");
				lstSelDrivepipe.Clear();
				foreach (Element item in enumerable)
				{
					lstSelDrivepipe.Add(item);
				}
				return true;
			}
			catch
			{
			}
			return false;
		}

		private string GetDrivePipeDimFamilyName(Element elemDrivePipe, bool bRightStyle = true)
		{
			string text = "";
			try
			{
				if ((elemDrivePipe as FamilyInstance).Symbol.Family.Name.Contains("穿墙"))
				{
					text = "穿墙套管标注";
				}
				else
				{
					text = "套管标注";
				}
				text += (bRightStyle ? "-右" : "-左");
			}
			catch
			{
			}
			return text;
		}

		private void DimSingleDrivepipe(UIDocument UIDoc, Element drivepipe)
		{
			if (!this.CanDimDrivepipe(drivepipe))
			{
				YJKMessageBox.Show("套管标注信息不完整.");
				return;
			}
			XYZ point = (drivepipe.Location as LocationPoint).Point;
			XYZ xyz = this.PickPointByBase(UIDoc, "请确定标注位置", point);
			if (xyz == null)
			{
				return;
			}
			string drivePipeDimFamilyName = this.GetDrivePipeDimFamilyName(drivepipe, xyz.X > point.X);
			FamilySymbol familySymbol = this.LoadDrivePipeDimFamily(UIDoc.Document, drivePipeDimFamilyName);
			if (familySymbol == null)
			{
				return;
			}
			this.ClearDrivepipeDim(UIDoc.Document, drivepipe.Id);
			this.CreateDrivePipeLabelDim(UIDoc.Document, familySymbol, drivepipe, point, xyz);
		}

		private void DimMultiDrivepipe(UIDocument UIDoc, List<Element> lstDrivepipe)
		{
			XYZ xyz = new XYZ(4.0, 4.0, 0.0);
			foreach (Element element in lstDrivepipe)
			{
				if (this.CanDimDrivepipe(element))
				{
					string drivePipeDimFamilyName = this.GetDrivePipeDimFamilyName(element, true);
					FamilySymbol familySymbol = this.LoadDrivePipeDimFamily(UIDoc.Document, drivePipeDimFamilyName);
					if (familySymbol != null)
					{
						XYZ point = (element.Location as LocationPoint).Point;
						this.ClearDrivepipeDim(UIDoc.Document, element.Id);
						this.CreateDrivePipeLabelDim(UIDoc.Document, familySymbol, element, point, point + xyz);
					}
				}
			}
		}

		private bool CanDimDrivepipe(Element drivepipe)
		{
			Parameter parameter = drivepipe.GetParameter("标注标高");
			if (parameter == null || string.IsNullOrEmpty(parameter.AsString()))
			{
				return false;
			}
			Parameter parameter2 = drivepipe.GetParameter("标注内容");
			return parameter2 != null && !string.IsNullOrEmpty(parameter2.AsString());
		}

		private FamilySymbol LoadDrivePipeDimFamily(Autodesk.Revit.DB.Document doc, string familyName)
		{
			FamilySymbol familySymbol = YJKRevitTools.GetFamilySymbol(familyName, doc);
			if (familySymbol != null)
			{
				return familySymbol;
			}
			Transaction transaction = new Transaction(doc);
			transaction.Start("LoadFamily");
			try
			{
				string text = Path.Combine(Product.FamilyLocation, RevitVersion.Version, "DrivepipeDim", familyName + ".rfa");
				doc.LoadFamily(text);
				familySymbol = YJKRevitTools.GetFamilySymbol(familyName, doc);
			}
			catch
			{
				YJKMessageBox.Show("加载族 " + familyName + " 失败！");
			}
			transaction.Commit();
			return familySymbol;
		}

		private void ClearDrivepipeDim(Autodesk.Revit.DB.Document doc, ElementId openingId)
		{
			Transaction transaction = new Transaction(doc, "DeleteInstance");
			transaction.Start();
			for (int i = 0; i < this.m_lstDrivepipeDim.Count; i++)
			{
				IndependentTag independentTag = this.m_lstDrivepipeDim[i];
				if (independentTag.TaggedLocalElementId == openingId)
				{
					doc.Delete(independentTag.Id);
					this.m_lstDrivepipeDim.Remove(independentTag);
					i--;
				}
			}
			transaction.Commit();
		}

		private void CreateDrivePipeLabelDim(Autodesk.Revit.DB.Document doc, FamilySymbol dimSymbol, Element drivePipe, XYZ ptPos, XYZ ptDim)
		{
			Transaction transaction = new Transaction(doc);
			transaction.Start("CreateDimTag");
			UnifiedModified.ActivateFamilySymbol(dimSymbol);
			IndependentTag independentTag = RevitVersionFuncs.NewTag(doc, doc.ActiveView, new Reference(drivePipe), false, 0, 0, ptDim);
			if (independentTag != null)
			{
				independentTag.ChangeTypeId(new ElementId(dimSymbol.Id.IntegerValue));
				independentTag.HasLeader = true;
                independentTag.LeaderEndCondition = (LeaderEndCondition)1;
				independentTag.LeaderEnd = ptPos;
				this.m_lstDrivepipeDim.Add(independentTag);
			}
			transaction.Commit();
		}

		private void GetAllOpeningDim(Autodesk.Revit.DB.Document doc)
		{
			this.m_lstDrivepipeDim = new List<IndependentTag>();
			foreach (Element element in YJKElementFilter.GetElementByClass(typeof(IndependentTag), doc))
			{
				IndependentTag independentTag = element as IndependentTag;
				if (independentTag != null && independentTag.TaggedLocalElementId != null)
				{
					this.m_lstDrivepipeDim.Add(independentTag);
				}
			}
		}

		private XYZ PickPointByBase(UIDocument UIDoc, string sCommandTip, XYZ ptBase)
		{
			List<ElementId> lstCurveId = new List<ElementId>();
			if (ptBase != null)
			{
				lstCurveId = this.DrawCrossFlag(UIDoc, ptBase);
			}
			try
			{
				XYZ xyz = UIDoc.Selection.PickPoint(sCommandTip);
				this.DeleteCrossFlag(UIDoc, lstCurveId);
				return new XYZ(xyz.X, xyz.Y, ptBase.Z);
			}
			catch
			{
				this.DeleteCrossFlag(UIDoc, lstCurveId);
			}
			return null;
		}

		private List<ElementId> DrawCrossFlag(UIDocument UIDoc, XYZ ptPos)
		{
			List<ElementId> list = new List<ElementId>();
			Transaction transaction = new Transaction(UIDoc.Document);
			transaction.Start("DrawCrossFlag");
			try
			{
				double num = AssistFunc.mmToFeet(200.0);
				CurveArray curveArray = new CurveArray();
				XYZ startPoint = new XYZ(ptPos.X - num, ptPos.Y + num, 0.0);
				XYZ endPoint = new XYZ(ptPos.X + num, ptPos.Y - num, 0.0);
				curveArray.Append(YJKLineEx.YJKGetBound(startPoint, endPoint));
				startPoint = new XYZ(ptPos.X + num, ptPos.Y + num, 0.0);
				endPoint = new XYZ(ptPos.X - num, ptPos.Y - num, 0.0);
				curveArray.Append(YJKLineEx.YJKGetBound(startPoint, endPoint));
				Autodesk.Revit.DB.View activeView = UIDoc.ActiveView;
				foreach (object obj in UIDoc.Document.Create.NewDetailCurveArray(activeView, curveArray))
				{
					DetailCurve detailCurve = (DetailCurve)obj;
					if (this.m_LineStyle != null)
					{
						detailCurve.LineStyle = this.m_LineStyle;
					}
					list.Add(detailCurve.Id);
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
			return list;
		}

		private void DeleteCrossFlag(UIDocument UIDoc, List<ElementId> lstCurveId)
		{
			Transaction transaction = new Transaction(UIDoc.Document, "DeleteTempElements");
			transaction.Start();
			foreach (ElementId elementId in lstCurveId)
			{
				UIDoc.Document.Delete(elementId);
			}
			transaction.Commit();
		}

		private GraphicsStyle m_LineStyle;

		private List<IndependentTag> m_lstDrivepipeDim;
	}
}
